package cn.xyt.server;

import static java.nio.ByteOrder.LITTLE_ENDIAN;

import java.nio.ByteOrder;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.tom.kit.IoBuffer;
import cn.xyt.dto.Header;
import cn.xyt.dto.Message;
import cn.xyt.util.ByteUtil;
import cn.xyt.util.NettyContextUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.DecoderException;

public class BaseInDecoder extends ByteToMessageDecoder{

	private final Logger logger = LoggerFactory.getLogger(BaseInDecoder.class);

    @Override
    protected final void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
    	if(in.readableBytes() < 2){
    		return;
    	}
    	in.markReaderIndex();
    	int len = in.order(ByteOrder.LITTLE_ENDIAN).readShort();
    	int readableSize = in.readableBytes();
    	if(readableSize < len){
    		in.resetReaderIndex();
    		String  id = (String)NettyContextUtil.getAttr(ctx, "id");
    		if(len>2000) {// 这个防止设备发送[T+CAT+CIPSEND=44.at+cpin?.]
    			byte [] temp =  new byte[readableSize];
    			in.readBytes(temp);
    			logger.error(id+ " ::clear length:: "+ ByteUtil.bytetoHexStr(temp));
    		}
    		if(readableSize>1000) { //累计多次协议错误断开
    			logger.error("bytebuf too long close id = {}", id);
    			ctx.close();  
    		}
    		return;
    	}
    	ByteBuf buf =  in.readBytes(len);
        out.add(toMassage(buf));
    }
    
    public Message toMassage(ByteBuf in){  //TODO 警告 使用 ByteBuf netty 引用需要自主释放
    	try{
    		/* 取22 字节的消息头*/
    		byte[] decoded = new byte[22];
    		in.readBytes(decoded);
    		Header header = toHeader(decoded);
    		/* 根据消息头取body的长度*/
    		byte[] body = new byte[header.getLength()];
    		in.readBytes(body);
    		/* 读取校验位*/
    		byte check = in.readByte();
    		Message message = new Message(header, body);
    		message.setCheck(check);
    		logger.info("decode msg header={} body={}", header);
    		return message;
    	}finally{
    		if(in != null) in.release();
    	}
    }
    
    /**
	 * 	消息ID msgid	 1
		消息体长度 length	2
		消息流水号 serial	2
		识别码 msgkey	12
		设备ID deviceid	4
		供应商代码supply	1
	 */
	private Header toHeader(byte[] decoded) {
		IoBuffer b = IoBuffer.allocate(decoded.length);
		b.buf.order(LITTLE_ENDIAN);
		b.writeBytes(decoded).flip();
		
		byte msgid = b.readByte(); //1 
		short length = b.readShort(); //2  
		short serial = b.readShort(); //2
		byte[] _msgkey = new byte[12]; //12
		b.readBytes(_msgkey);
		String msgkey = new String(_msgkey);
		int deviceid = b.readInt(); //4
		byte supply = b.readByte(); //1
		Header header = new Header();
		header.setMsgid(msgid);
		header.setLength(length);
		header.setDeviceid(deviceid);
		header.setMsgkey(msgkey);
		header.setSerial(serial);
		header.setSupply(supply);
		return header;
	}
	
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		String  id = (String)NettyContextUtil.getAttr(ctx, "id");
		logger.error(id + "::BaseInDecoder.exceptionCaught::", cause);
		if(cause instanceof DecoderException){
			ctx.close();
		}
	}
	
	
    
}
